//
// Created by QU on 24-6-24.
//
#include <iostream>
#include <functional>
#include <utility>
#include <memory>
#include <vector>
#include <map>
#include <set>
#include <new>
#include <thread>
#include <algorithm>
#include <array>
#include <string>
#include <deque>

using std::cout, std::cin, std::endl;

// 在现代C++中，常量表达式（constant expressions）是指在编译时能够计算出结果的表达式。常量表达式有助于提高程序的效率和安全性，因为它们可以在编译阶段进行计算，从而避免运行时开销。
// C++11引入了constexpr关键字，用于定义常量表达式，并在C++14和C++17中进行了扩展和改进。

// constexpr 关键字
// constexpr关键字用于指示一个函数或变量可以在编译时求值。如果一个函数或变量被标记为constexpr，编译器将在编译阶段尝试计算其结果。如果无法在编译时计算，则会产生编译错误。

// constexpr 变量
// constexpr变量必须在声明时初始化，并且其初始化表达式必须是常量表达式。

/*
constexpr int square(int x) {
    return x * x;
}

int main() {
    constexpr int result = square(5); // 在编译时计算
    return 0;
}
*/

// constexpr 函数
// constexpr函数的所有参数和返回值必须是常量表达式，并且函数体内只能包含能在编译时求值的操作。

/*
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : (n * factorial(n - 1));
}

int main() {
    constexpr int result = factorial(5); // 在编译时计算
    return 0;
}
*/

// C++14 中的改进
// C++14 对constexpr函数进行了改进，允许在函数体内使用更多种类的语句，如循环和局部变量。这使得编写复杂的constexpr函数变得更加容易。

/*
constexpr int fibonacci(int n) {
    int a = 0, b = 1;
    for (int i = 0; i < n; ++i) {
        int temp = a;
        a = b;
        b = temp + b;
    }
    return a;
}

int main() {
    constexpr int result = fibonacci(10); // 在编译时计算
    return 0;
}
*/

// C++17 中的改进
// C++17 进一步扩展了constexpr的使用范围，允许更多的标准库函数和容器在常量表达式中使用。

// constexpr if 语句
// C++17 引入了constexpr if语句，用于在编译时选择性地执行代码分支。

/*
template <typename T>
constexpr T max(T a, T b) {
    if constexpr (std::is_integral<T>::value) {
        return (a > b) ? a : b;
    } else {
        return (a + b) / 2; // 假设 T 是浮点类型
    }
}

int main() {
    constexpr int result = max(10, 20); // 在编译时计算
    return 0;
}
*/

// constexpr 与 const
// constexpr：指示一个值可以在编译时求值，主要用于编译时常量表达式的计算。constexpr变量和函数在编译时进行求值，并且结果也是常量。
// const：指示一个值在初始化后不能被修改。const变量不一定在编译时求值，可以在运行时初始化。

/*
constexpr int compileTimeConstant = 10; // 编译时常量
const int runTimeConstant = someFunction(); // 运行时常量，取决于someFunction的结果
*/

// 实践中的应用
// 数组大小：使用constexpr计算数组的大小。
// 元编程：利用constexpr进行模板元编程，实现复杂的编译时计算。
// 配置与优化：通过编译时计算常量，减少运行时开销，提高程序性能。
// 示例：常量表达式的实际应用
// 以下示例展示了如何使用constexpr来计算矩阵的行列式（determinant），并在编译时进行优化。

/*
#include <iostream>

constexpr int determinant(int a, int b, int c, int d) {
    return a * d - b * c;
}

int main() {
    constexpr int det = determinant(1, 2, 3, 4); // 在编译时计算
    std::cout << "Determinant: " << det << std::endl;
    return 0;
}
*/

// 总结
// 现代C++中的常量表达式通过constexpr关键字实现，允许在编译时计算表达式，从而提高程序的效率和安全性。
// C++14和C++17对constexpr的功能进行了扩展，使其更加灵活和强大。
// 在实际编程中，constexpr可以用于优化代码、提高性能、减少运行时开销，是C++开发者需要掌握的重要特性。

// 定义 constexpr 函数
constexpr int add(int a, int b)
{
    return a + b;
}

int main()
{
    // 在编译时求值，result1 是一个常量表达式
    constexpr int result1 = add(2, 3);
    std::cout << "Compile-time result: " << result1 << std::endl;

    // 在运行时求值，因为参数不是常量表达式
    int x = 5;
    int y = 10;
    int result2 = add(x, y);
    std::cout << "Runtime result: " << result2 << std::endl;

    return 0;
}
